package com.fowo.api.common.config;

import org.jetbrains.annotations.NotNull;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.time.Duration;
import java.util.Objects;

/**
 * 缓存配置
 * @author yl_ls
 */
@EnableCaching
@Configuration
public class CacheConfig {

    /**
     * 快速缓存名称，缓存 1 分钟
     */
    public static final String FASTEST = "fastest";

    /**
     * 快速缓存名称，缓存 5 分钟
     */
    public static final String FAST = "fast";

    /**
     * 快速缓存名称，缓存 10 分钟
     */
    public static final String M10 = "10min";

    /**
     * 快速缓存名称，缓存 15 分钟
     */
    public static final String M15 = "15min";

    /**
     * 快速缓存名称，缓存 30 分钟
     */
    public static final String M30 = "30min";

    /**
     * 快速缓存名称，缓存 1 小时
     */
    public static final String H1 = "1hour";

    /**
     * 快速缓存名称，缓存 2 小时
     */
    public static final String H2 = "2hour";

    /**
     * 快速缓存名称，缓存 8 小时
     */
    public static final String H8 = "8hour";

    /**
     * 快速缓存名称，缓存 1 天
     */
    public static final String D1 = "1day";

    /**
     * 长时间缓存名称，缓存 30 天
     */
    public static final String LONG = "long";

    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> template) {
        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(Objects.requireNonNull(template.getConnectionFactory()))
                .cacheDefaults(getRedisCacheConfiguration(template, Duration.ofHours(1)))
                .withCacheConfiguration(FASTEST, getRedisCacheConfiguration(template, Duration.ofMinutes(1)))
                .withCacheConfiguration(FAST, getRedisCacheConfiguration(template, Duration.ofMinutes(5)))
                .withCacheConfiguration(M10, getRedisCacheConfiguration(template, Duration.ofMinutes(10)))
                .withCacheConfiguration(M15, getRedisCacheConfiguration(template, Duration.ofMinutes(15)))
                .withCacheConfiguration(M30, getRedisCacheConfiguration(template, Duration.ofMinutes(30)))
                .withCacheConfiguration(H1, getRedisCacheConfiguration(template, Duration.ofHours(1)))
                .withCacheConfiguration(H2, getRedisCacheConfiguration(template, Duration.ofHours(2)))
                .withCacheConfiguration(H8, getRedisCacheConfiguration(template, Duration.ofHours(8)))
                .withCacheConfiguration(D1, getRedisCacheConfiguration(template, Duration.ofDays(1)))
                .withCacheConfiguration(LONG, getRedisCacheConfiguration(template, Duration.ofDays(30)))
                .transactionAware()
                .build();
    }

    @NotNull
    private static RedisCacheConfiguration getRedisCacheConfiguration(RedisTemplate<String, Object> template, Duration ttl) {
        return RedisCacheConfiguration
                .defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()))
                .entryTtl(ttl);
    }
}
